
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#include "bmap.h"
#include "bmap_fetch.h"
#include "bmap_generator.h"
#include "bmap_parse.h"
#include "bmap_replay.h"
#include "bmap_seeksim.h"

#include "dir.h"


/*

#define LBA_FILE "lba.txt"

int read_file(const char *filename)
{
	struct bmap *bm;
	FILE *fp;
	if(!(fp=fopen(filename, "r"))){
		fprintf(stderr, "Error: cann't open file '%s'\n", filename);
		return -1;
	}
	printf("Reading from file '%s'\n", filename);
	// reading line by line:
	while((bm = bmap_load(fp))!=NULL){
		//bmap_show(bm);
		bmap_save(bm, stdout);
		bmap_destroy(bm);
	}
	fclose(fp);
	return 0;
}

int process_file(const char *filename)
{
	long blksize;
	uint64_t blkcnt, offset;
	double seeksim_t_real, seeksim_t_ideal;
	double replay_t_real, replay_t_ideal;
	double seeksim_df, replay_df;
	struct bmap *bm;
	//real file data:
	bm = bmap_fetch(filename);
	blkcnt = bm->blkcnt;
	blksize = bm->blksize;
	offset = bm->head->offset;
	bmap_save(bm, stdout);
	//bmap_analyze(bm);
	seeksim_t_real = bmap_seeksim(bm);
	replay_t_real = bmap_replay(bm, "/dev/sda1");
	bmap_destroy(bm);

	// ideal file:
	bm = bmap_create("ideal", blksize);
	bmap_append(bm, offset * 0, blkcnt);
	seeksim_t_ideal = bmap_seeksim(bm);
	replay_t_ideal = bmap_replay(bm, "/dev/sda1");
	bmap_destroy(bm);

	// compute:
	seeksim_df = seeksim_t_real / seeksim_t_ideal;
	replay_df = replay_t_real / replay_t_ideal;
	printf("SeekSim DF: %lf \t %lf ms \t %lf ms\n", seeksim_df, seeksim_t_real, seeksim_t_ideal);
	printf("Replay  DF: %lf \t %lf ms \t %lf ms\n", replay_df, replay_t_real, replay_t_ideal);
	return 0;
}

int main(int argc, char *argv[])
{

	char *source;
	if(argc!=2){
		source = argv[0];
	}else{
		source = argv[1];
	}
	if(isdir(source)){
		dir_scan(source, process_file);
	}else{
		process_file(source);
	}

	return 0;
}

*/







//*******************************************************************************************
static int verbose = 0;
static int handle_bmap(struct bmap *bm)
{
	
	if(verbose){
		bmap_save(bm, stdout);
	}
	parsers_bmap(bm);
	return 0;
}


//*******************************************************************************************
static int fetch_file(const char *filename)
{
	struct bmap *bm;
	bm = bmap_fetch(filename);
	handle_bmap(bm);
	bmap_destroy(bm);
	return 0;
}

//*******************************************************************************************

static int process_fetch(const char *path)
{
	parsers_start(path);
	if(isdir(path)){
		dir_scan(path, fetch_file);
	}else{
		fetch_file(path);
	}
	parsers_report();
	return 0;
}

static int process_generator(const char *generator)
{
	parsers_start(generator);
	parsers_report();
	return 0;
}

static int process_bmap(const char *bmapfile)
{
	struct bmap *bm;
	FILE *fp;
	parsers_start(bmapfile);
	if(!(fp=fopen(bmapfile, "r"))){
		fprintf(stderr, "Error: cann't open file '%s'\n", bmapfile);
		exit(-1);
	}
	// reading line by line:
	while((bm = bmap_load(fp))!=NULL){
		handle_bmap(bm);
		bmap_destroy(bm);
	}
	fclose(fp);
	parsers_report();
	return 0;
}

//***************************************************************************************

#include <stdio.h>  
#include <getopt.h> 

static char prog_version[] = "0.01";

static char prog_usage[] = "\n" \
	"\tUsage: bmap [-v] [-f fetch_target] [-g generate_args] [-i bmap_sources] [-p parse_args] [fetch_targets]\n" \
	"\tUsage: bmap -h\n" \
	"\n";
 
static const char* short_options = "f:g:hi:p:rst:v";  
static struct option long_options[] = {
	{ "fetch",    		1,   NULL,    'f'},
	{ "generate", 		1,   NULL,    'g'},  
	{ "help",	  		0,   NULL,    'h'},  
	{ "input",    		1,   NULL,    'i'},
	{ "parse",    		1,   NULL,    'p'},
	{ "fmt_percentage",	0,   NULL,    'r'},
	{ "fmt_sequential",	0,	 NULL,	  's'},
	{ "fmt_step",		1,   NULL,    't'},
	{ "verbose",  		0,   NULL,    'v'},
	{      0,     		0,      0,      0} 
};  

static void usage(char *prog)
{
	fprintf(stderr,"Usage: %s %s %s", prog, prog_version, prog_usage);
}

#define MAX_ARGSCNT  255

int main(int argc, char *argv[])  
{
	assert(argc < MAX_ARGSCNT);
	extern int step_format, percentage_format, sequential_format;

	const char *fetches[MAX_ARGSCNT], *generators[MAX_ARGSCNT], *bmaps[MAX_ARGSCNT], *parsers[MAX_ARGSCNT];
	int fetches_cnt = 0;
	int generators_cnt = 0;
	int bmaps_cnt = 0;
	int parsers_cnt = 0;
	int i;

	int c; /* optarg, optind */ 
	while((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1){  
		switch (c){
		case 'f':
			fetches[fetches_cnt++] = optarg;
			break;
		case 'g':
			generators[generators_cnt++] = optarg;
			break;
		case 'h':
			usage(argv[0]);
			return 1;
		case 'i':  
			bmaps[bmaps_cnt++] = optarg; 
			break;
		case 'p':
			parsers[parsers_cnt++] = optarg;
			break;
		case 'r':
			percentage_format = 1;
			break;
		case 's':
			sequential_format = 1;
			break;
		case 't':
			step_format = atoi(optarg);
			break;
		case 'v':
			verbose = 1;
			break;
		default:
			//usage(argv[0]);
			//error info will be given automatically by getopt_long()... 
			return -1;
		}  
	}
	while(optind < argc){
		/* process 'argv[optind]' here */
		fetches[fetches_cnt++] = argv[optind];
		optind++;
	}
	// initialize the parsers:
	for(i=0; i<parsers_cnt; i++){
		if(!parsers_enable(parsers[i])){
			fprintf(stderr, "Unknown parsers: %s\n", parsers[i]);
		}else{
			fprintf(stderr, "Enable parsers: %s\n", parsers[i]);
		}
	}
	
	//begin the process:
	for(i=0; i<fetches_cnt; i++){
		process_fetch(fetches[i]);
	}

	for(i=0; i<generators_cnt; i++){
		process_generator(generators[i]);
	}

	for(i=0; i<bmaps_cnt; i++){
		if(isdir(bmaps[i])){
			dir_scan(bmaps[i], process_bmap);
		}else{
			process_bmap(bmaps[i]);
		}
	}
	return 0;  
} 

